package com.cnswhy.cloud.server.app.controller.notify;

import com.alibaba.fastjson.JSON;
import com.alipay.api.internal.util.AlipaySignature;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.core.utils.CnswhyUtil;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.app.controller.BaseController;
import com.cnswhy.cloud.server.common.entity.enumeration.PayType;
import com.cnswhy.cloud.server.core.appservice.AppChargeMoneyService;
import com.cnswhy.cloud.server.core.appservice.AppSpellOrderService;
import com.cnswhy.cloud.server.core.config.AlipayConfig;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.service.ChargeMoneyService;
import com.cnswhy.cloud.server.core.service.SysConfigService;
import com.cnswhy.cloud.server.core.service.shop.ShopOrderService;
import com.cnswhy.cloud.server.core.service.spell.BuyBackOrderService;
import com.cnswhy.cloud.server.core.service.spell.SpellOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 描述: 阿里支付回调
 * 版权: Copyright (c) 2019
 * 公司: 小鹿科技
 * 作者: 张润泽
 * 版本: 1.0
 * 创建日期: 2019年11月19日
 * 创建时间: 下午5:26:23
 */
@Controller
@RequestMapping("/aliPayNotify")
@Slf4j
public class AliPayNotify extends BaseController {


    @Autowired
    private RedisService redisService;


    @Autowired
    private ShopOrderService shopOrderService;


    @Autowired
    private ChargeMoneyService chargeMoneyService;

    @Autowired
    private BuyBackOrderService buyBackOrderService;

    @Autowired
    private SpellOrderService spellOrderService;
    @Autowired
    AppChargeMoneyService appChargeMoneyService;
    @Autowired
    AppSpellOrderService appSpellOrderService;
    @Autowired
    SysConfigService sysConfigService;


    @SuppressWarnings("rawtypes")
    @PostMapping("/notify")
    public void appAliPayNotify(HttpServletRequest request, HttpServletResponse response) {
        log.error("============================支付宝回调开始");
        response.setCharacterEncoding("UTF-8");
        //设置字符流编码，而且还会添加content-Type响应头，这个头通知浏览器用utf-8解码。
        response.setContentType("text/html;charset=utf-8");

        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }

        log.error("收到支付宝支付回调，内容：" + JSON.toJSONString(params));
        try {
            // 返回success
            PrintWriter out = response.getWriter();
            out.print("success");
            out.flush();
            out.close();

            // 商户订单号
            String outTradeNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 支付宝交易号
            String tradeNo = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 交易状态
            String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
            // 交易金额
            String totalAmount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
            // 用于区分支付的业务类型
            String body = new String(request.getParameter("body").getBytes("ISO-8859-1"), "UTF-8");

            /*BigDecimal orderPrice = BigDecimal.ZERO;
            ShopOrder queryByOrderNo = shopOrderService.getOne(Wraps.<ShopOrder>lbQ().eq(ShopOrder::getChannelOrderId,outTradeNo));
            orderPrice = queryByOrderNo.getOrderPrice();*/


            // 调用SDK验证签名
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "aliPaySys").eq(SysConfig::getDisplayStatus, "1"));
            boolean flag = AlipaySignature.rsaCheckV1(params, sysConfig.getConfigRules(), AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);
            String info = "flag = " + flag + ";out_trade_no = " + outTradeNo + ";trade_no" + tradeNo
                    + ";trade_status = " + tradeStatus + ";total_amount=" + totalAmount + ";body=" + body;
            log.info("支付宝回调返回参数：" + info);

            if (flag && this.validateOrderNo(outTradeNo)) {
                // 交易结束、超时或全额退款时返回的状态，由于退款状态有单独的查询任务，故不处理此回调状态
                if ("TRADE_FINISHED".equals(tradeStatus) || "TRADE_CLOSED".equals(tradeStatus)) {
                    return;
                }

                // 订单金额一致，判断订单状态
                if ("TRADE_SUCCESS".equals(tradeStatus)) {
                    if("UPGRADE".equals(body)){
                        appSpellOrderService.upgradeOrder(tradeNo, outTradeNo, PayType.alipay);
                    }else{
                        appSpellOrderService.saveOrderNotify(outTradeNo, tradeNo);
                    }
                }
                // 失败
                else {
                    log.info("【注意】名品名店订单号为" + outTradeNo + "的微信支付回调状态为失败，错误码：" + tradeStatus);
                }

            }
        } catch (Exception e) {
            log.error("支付宝支付回调异常：", e);
        }
    }

    /**
     * 描述：防止回调重复，校验redis中是否已经存在此订单
     * 作者：张润泽
     * 时间：2019年3月19日 上午10:48:42
     *
     * @param orderNo
     * @return true 不存在此订单  false 已存在此订单
     */
    private boolean validateOrderNo(String orderNo) {
        String order = (String) redisService.get(orderNo);
        if (StringUtils.isBlank(order)) {
            // 将订单号放入redis中60分钟
            redisService.set(orderNo, "60");
            redisService.expire(orderNo, 600L);
            return true;
        }
        return false;
    }
}
